package com.zhike.common.utils;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import cn.hutool.core.io.file.FileNameUtil;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.StringTokenizer;


public class FileHelper {
	protected static Log log = LogFactory.getLog(FileHelper.class);

	public static void main(String[] args) {
		log.info(getFileExt("xxxx.jpg"));
	}

	public static boolean isFile(String filename) {
		File tmpfile = new File(filename);
		return tmpfile.exists() && tmpfile.isFile();
	}

	public static boolean isDir(String filename) {
		File tmpfile = new File(filename);
		return tmpfile.exists() && tmpfile.isDirectory();
	}

	public static String readTextFileSkipComments(String filename,
			String encode, String commentprefix) {
		StringBuilder tmpsb = new StringBuilder();
		InputStream tmpin = null;
		BufferedReader bufRead = null;
		try {
			tmpin = FileHelper.class.getResourceAsStream(filename);
			bufRead = new BufferedReader(new InputStreamReader(tmpin, encode));
			String str;
			while ((str = bufRead.readLine()) != null) {
				if (!str.startsWith(commentprefix))
					tmpsb.append(str);
			}
		} catch (Exception ioe) {

		} finally {
			try {
				if (bufRead != null)
					bufRead.close();
			} catch (Exception ex11) {
			}
			try {
				if (tmpin != null)
					tmpin.close();
			} catch (Exception ex12) {
			}
		}
		return tmpsb.toString();
	}

	public static String getFilename(String filename) {
		String tmpret = "";
		filename = filename.replaceAll("\\\\", "/");
		int tmpindex = filename.lastIndexOf("/");
		if (tmpindex != -1) {
			tmpret = filename.substring(tmpindex + 1);
		} else
			tmpret = filename;
		return tmpret;
	}

	public static String getFileExt(String filename) {
		String tmpext = "";
		if ((filename != null) && (!"".equals(filename))) {
			int tmpindex = filename.lastIndexOf(".");
			if (tmpindex != -1) {
				int tmpindex2 = filename.indexOf("?", tmpindex + 1);
				if (tmpindex2 == -1)
					tmpindex2 = filename.length();
				tmpext = filename.substring(tmpindex, tmpindex2);
			}
		}
		return tmpext;
	}

	/***
	 * 速度最快的，除了那个byteMapFileCopy
	 * 
	 * @param src
	 * @param dst
	 */
	public static int nioTransferCopy(String src, String dst) {
		int tmpret = -1;
		File source = null;
		File target = null;
		FileChannel in = null;
		FileChannel out = null;
		FileInputStream inStream = null;
		FileOutputStream outStream = null;

		try {
			source = new File(src);
			target = new File(dst);
			long t1 = System.currentTimeMillis();
			inStream = new FileInputStream(source);
			outStream = new FileOutputStream(target);
			in = inStream.getChannel();
			out = outStream.getChannel();
			in.transferTo(0, in.size(), out);
			log.info("花费时间" + (System.currentTimeMillis() - t1)
					+ "毫秒拷贝");
			tmpret = 0;
		} catch (Exception e) {
			log.error(e);
		} finally {
			try {
				if (inStream != null)
					inStream.close();
			} catch (Exception ex1) {
			}
			try {
				if (in != null)
					in.close();
			} catch (Exception ex2) {
			}
			try {
				if (outStream != null)
					outStream.close();
			} catch (Exception ex3) {
			}
			try {
				if (out != null)
					out.close();
			} catch (Exception ex4) {
			}
		}
		return tmpret;
	}

	public static int nioBufferCopy(String src, String dst) {
		int tmpret = -1;
		try {
			File tmpsrc = new File(src);
			if (tmpsrc.exists()) {
				long t1 = System.currentTimeMillis();
				File tmpdst = new File(dst);
				tmpret = nioBufferCopy(tmpsrc, tmpdst);
				log.info("花费时间" + (System.currentTimeMillis() - t1)
						+ "毫秒拷贝");

			}
		} catch (Exception ex) {
			log.error(ex);
		}
		return tmpret;
	}

	public static int nioBufferCopy(File source, File target) {
		int tmpret = -1;
		FileChannel in = null;
		FileChannel out = null;
		FileInputStream inStream = null;
		FileOutputStream outStream = null;
		try {
			inStream = new FileInputStream(source);
			outStream = new FileOutputStream(target);
			in = inStream.getChannel();
			out = outStream.getChannel();
			ByteBuffer buffer = ByteBuffer.allocate(4096);
			while (in.read(buffer) != -1) {
				buffer.flip();
				out.write(buffer);
				buffer.clear();
			}
			tmpret = 0;
		} catch (Exception e) {
			log.error(e);
		} finally {
			try {
				if (inStream != null)
					inStream.close();
			} catch (Exception ex1) {
			}
			try {
				if (in != null)
					in.close();
			} catch (Exception ex2) {
			}
			try {
				if (outStream != null)
					outStream.close();
			} catch (Exception ex3) {
			}
			try {
				if (out != null)
					out.close();
			} catch (Exception ex4) {
			}
		}
		return tmpret;
	}

	/**
	 * 对小文件拷贝20-200M的，太大了比较消耗内存
	 * 
	 * @param inFile
	 * @param outFile
	 * @return
	 */
	public static int byteMapFileCopy(String inFile, String outFile) {
		int tmpret = -1;
		FileChannel out = null;
		File file = null;
		MappedByteBuffer buffer = null;
		try {
			long t1 = System.currentTimeMillis();
			file = new File(inFile);
			out = new FileOutputStream(new File(outFile)).getChannel();
			buffer = new FileInputStream(file).getChannel().map(
					FileChannel.MapMode.READ_ONLY, 0, file.length());
			buffer.load();
			out.write(buffer);
			buffer = null;
			out.close();
			log.info("花费时间" + (System.currentTimeMillis() - t1)
					+ "毫秒拷贝");
			tmpret = 0;
		} catch (Exception ex) {
			log.error("byteMapFileCopy:" + ex);
		} finally {
			if (out != null) {
				try {
					out.close();
				} catch (Exception ex11) {
				}
			}
		}
		return tmpret;
	}

	public static void deleteFile(File file) {
		if (file.exists())
			file.delete();
	}

	public static void deleteDir(String dirname) {
		deleteDir(new File(dirname));
	}

	public static long getFileOrDirSizeInM(String filename) {
		return getFileOrDirSizeInM(new File(filename));
	}

	public static long getFileOrDirSizeInM(File file) {
		long tmpsize = 0;
		if (file.exists()) {
			if (file.isFile()) {
				if (file.length() < 1048576)
					tmpsize = 1;
				else
					tmpsize = Math.round(file.length() / 1048576.0);// 转换成M
			} else {
				File[] files = file.listFiles();
				for (int i = 0; i < files.length; i++) {
					if (files[i].isFile())
						if (files[i].length() < 1048576)
							tmpsize += 1;
						else
							tmpsize += Math
									.round(files[i].length() / 1048576.0);// 转换成M
					else {// dir
						tmpsize += getFileOrDirSizeInM(files[i]);
					}
				}
			}
		}
		return tmpsize;
	}

	public static void deleteDir(File file) {
		if (file.exists()) {
			File[] files = file.listFiles();
			for (int i = 0; i < files.length; i++) {
				File file1 = files[i];
				if (!file1.isDirectory()) {
					deleteFile(file1);
				} else {
					deleteDir(file1);
				}
			}
			file.delete();
		}
	}

	public static void deleteFile(String filename) {
		try {
			File tmpfile = new File(filename);
			if (tmpfile.isDirectory()) {
				deleteDir(tmpfile);
			} else {
				if (tmpfile.exists()) {
					tmpfile.delete();
				}
			}
		} catch (Exception ex) {
			log.error(ex);
		}
	}

	public static long getFileSize(String filename) {
		long tmpret = 0;

		try {
			File tmpfile = new File(filename);

			if (tmpfile.exists()) {
				tmpret = tmpfile.length();
			}
		} catch (Exception ex) {
			log.error(ex);
			tmpret = 0;
		}

		return tmpret;
	}

	public static boolean exist(String filename) {
		boolean tmpret = false;
		try {
			File tmpfile = new File(filename);
			if (tmpfile.exists()) {
				tmpret = true;
			}
		} catch (Exception ex) {
			log.error(ex);
			tmpret = false;
		}
		return tmpret;
	}

	public static void copyDir(File from, File to) {
		if (!to.exists()) {
			to.mkdirs();
		}
		File[] files = from.listFiles();
		for (int i = 0; i < files.length; i++) {
			File file1 = files[i];
			File file2 = new File(to.getPath() + File.separator
					+ files[i].getName());
			if (!file1.isDirectory()) {
				copyFile(file1, file2);
			} else {
				copyDir(file1, file2);
			}
		}

	}

	public static int copyFile(String src, String dest) {
		// return byteMapFileCopy(src,dest);
		// return copyFile(new File(src), new File(dest));
		// 不再使用慢的拷贝速度，采用高速的拷贝方式
		return nioTransferCopy(src, dest);
	}

	public static int copyFile(File src, File dest) {
		int tmpret = 0;
		try {
			int tmpreadlen = 0;
			FileInputStream in = new FileInputStream(src);
			FileOutputStream out = new FileOutputStream(dest);
			byte[] buffer = new byte[1024];
			while ((tmpreadlen = in.read(buffer)) != -1) {
				out.write(buffer, 0, tmpreadlen);
			}
			out.close();
			in.close();
			log.info("文件拷贝成功");
		} catch (Exception e) {
			log.info("文件拷贝失败");
			tmpret = -1;
		}

		return tmpret;
	}

	public static String extractPath(String urlStr) {
		try {
			// 创建 URL 对象
			URL url = new URL(urlStr);
			// 获取 URL 的路径部分
			String path = url.getPath();
			// 如果路径为空，返回根路径 "/"
			return path.isEmpty() ? "/" : path;
		} catch (MalformedURLException e) {
			// 若 URL 格式错误，打印错误信息并返回原字符串
			System.err.println("Invalid URL: " + urlStr);
			return urlStr;
		}
	}

	/**
	 * 获得文件后缀名，扩展名不带“.”
	 *
	 * @param fileName 文件名
	 * @return 扩展名
	 * @see FileNameUtil#getSuffix(String)
	 * @since 5.3.8
	 */
	public static String getSuffix(String fileName) {
		return FileNameUtil.getSuffix(fileName);
	}

	public static void checkPathExist(String path) {
		String tmppath = path;

		if (path.indexOf(".") > 0)
			tmppath = path.substring(0, path.lastIndexOf("/"));
		if (!tmppath.endsWith("/"))
			tmppath += "/";

		log.info("CheckPath Exist:" + path);
		// remove file if exist
		File file = new File(tmppath);

		if (!file.exists()) {

			if (!file.mkdir()) {

				if (!tmppath.endsWith("/")) {
					int tmpindex = path.lastIndexOf("/", path.length());
					if (tmpindex != -1) {
						tmppath = tmppath.substring(0, tmpindex);
					}
				}

				if (tmppath.indexOf(":") != -1)// widnows style include
				// c://test/test/test.zip
				{
					StringTokenizer st = new StringTokenizer(tmppath, "/");
					String path1 = st.nextToken() + "/";
					String path2 = path1;
					while (st.hasMoreTokens()) {
						path1 = st.nextToken() + "/";
						path2 += path1;
						File inbox = new File(path2);
						if (!inbox.exists())
							inbox.mkdir();
					}
				} else {
					File inbox = new File(tmppath);
					if (!inbox.exists()) {
						inbox.mkdirs();
					}
				}
			}
		}

	}

}
